package com.auth.config.code;

import com.redis.RedisUtil;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;

/**
 *  基于Redis 生成存储token实现类
 * @author: hw
 * @date: 2021/11/25 10:40
 */
public class RedisAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {

    private RandomValueStringGenerator generator = new RandomValueStringGenerator(8);

    public static final String AUTH_CODE_PREFIX = "AUTH_CODE_PREFIX";

    private final RedisUtil redisUtils;

    public RedisAuthorizationCodeServices(RedisUtil redisUtil) {
        this.redisUtils = redisUtil;
    }

    /**
     * 设置code长度
     * @param authentication
     * @return
     */
    @Override
    public String createAuthorizationCode(OAuth2Authentication authentication) {
        String code = generator.generate();
        this.store(code, authentication);
        return code;
    }

    @Override
    public OAuth2Authentication consumeAuthorizationCode(String code)
            throws InvalidGrantException {
        OAuth2Authentication auth = this.remove(this.getCodeKey(code));
        if (auth == null) {
            throw new InvalidGrantException("Invalid authorization code: " + code);
        }
        return auth;
    }

    /**
     * 存储code 默认有效时间60秒
     *  如60秒没有使用则直接过期
     * @param code
     * @param authentication
     */
    @Override
    protected void store(String code, OAuth2Authentication authentication) {
        redisUtils.set(this.getCodeKey(code),authentication,600);
    }

    /**
     * 根据code 获取OAuth2Authentication 对象并返回
     * @param code
     * @return
     */
    @Override
    protected OAuth2Authentication remove(String code) {
        OAuth2Authentication authentication;
        try {
            if (redisUtils.hasKey(code)){
                authentication = (OAuth2Authentication)redisUtils.get(code);
            }else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }

        if (authentication != null) {
            redisUtils.del(code);
        }
        return authentication;
    }

    private String getCodeKey(String code){
        return AUTH_CODE_PREFIX+":"+code;
    }
}
